﻿/*=============================================================================
* File Name : Matrix3.cpp                         Ver : 1.00  Date : 2009-3-26
*
* Description :
*
*       ３行３列座標変換行列計算　ソース
*
* Author : 土田　悠貴.
*============================================================================*/
#include "Matrix3.h"
#include "Math.h"
#include "Vector2.h"
#include "Vector3.h"
#include "Quaternion.h"
#include "../utility/Plane.h"
#include "Matrix4.h"

namespace tglib
{

/*===========================================================================*/
/**
 * コンストラクタ．
 */
Matrix3::Matrix3()
{
	m[0][0] = 0.0f; m[0][1] = 0.0f; m[0][2] = 0.0f;
	m[1][0] = 0.0f; m[1][1] = 0.0f; m[1][2] = 0.0f;
	m[2][0] = 0.0f; m[2][1] = 0.0f; m[2][2] = 0.0f;
}

/*===========================================================================*/
/**
 * コンストラクタ．
 *
 * @param [in]     m11～m33　行列の各成分．
 */
Matrix3::Matrix3
(
	float m11, float m12, float m13, 
	float m21, float m22, float m23,
	float m31, float m32, float m33 
)
{
	m[0][0]= m11; m[0][1] = m12; m[0][2] = m13;
	m[1][0]= m21; m[1][1] = m22; m[1][2] = m32;
	m[2][0]= m31; m[2][1] = m32; m[2][2] = m33;
}

/*===========================================================================*/
/**
 * コンストラクタ．
 *
 * @param [in]     axisX　X軸の成分．
 * @param [in]     axisY　Y軸の成分．
 * @param [in]     axisZ　Z軸の成分．
 */
Matrix3::Matrix3
( 
	const Vector3& axisX,
	const Vector3& axisY,
	const Vector3& axisZ
)
{
	m[0][0]= axisX.x; m[0][1] = axisX.y; m[0][2] = axisX.z;
	m[1][0]= axisY.x; m[1][1] = axisY.y; m[1][2] = axisY.z;
	m[2][0]= axisZ.x; m[2][1] = axisZ.y; m[2][2] = axisZ.z;
}

/*===========================================================================*/
/**
 * コンストラクタ．
 *
 * @param [in]    p　9行配列．
 */
Matrix3::Matrix3( const float* p )
{
	m[0][0]= p[0]; m[0][1] = p[1]; m[0][2] = p[2];
	m[1][0]= p[3]; m[1][1] = p[4]; m[1][2] = p[5];
	m[2][0]= p[6]; m[2][1] = p[7]; m[2][2] = p[8];
}

/*===========================================================================*/
/**
 * コンストラクタ．
 *
 * @param [in]    M　4行4列構造体．
 */
Matrix3::Matrix3( const Matrix4& M )
{
	m[0][0]= M.m[0][0]; m[0][1] = M.m[0][1]; m[0][2] = M.m[0][2];
	m[1][0]= M.m[1][0]; m[1][1] = M.m[1][1]; m[1][2] = M.m[1][2];
	m[2][0]= M.m[2][0]; m[2][1] = M.m[2][1]; m[2][2] = M.m[2][2];
}

/*===========================================================================*/
/**
 * コンストラクタ．
 *
 * @param [in]    q　クォータニオン．
 */
Matrix3::Matrix3( const Quaternion& q )
{
	float		xx, yy, zz;
	float		xy, xz, yz;
	float		wx, wy, wz;

	xx = q.x * q.x * 2.0f;
	yy = q.y * q.y * 2.0f;
	zz = q.z * q.z * 2.0f;
	xy = q.x * q.y * 2.0f;
	xz = q.x * q.z * 2.0f;
	yz = q.y * q.z * 2.0f;
	wx = q.w * q.x * 2.0f;
	wy = q.w * q.y * 2.0f;
	wz = q.w * q.z * 2.0f;

	m[0][0] = 1.0f - ( yy + zz );
	m[0][1] = xy + wz;
	m[0][2] = xz - wy;

	m[1][0] = xy - wz;
	m[1][1] = 1.0f - ( xx + zz );
	m[1][2] = yz + wx;

	m[2][0] = xz + wy;
	m[2][1] = yz - wx;
	m[2][2] = 1.0f - ( xx + yy );
	m[2][3] = 0.0f;
}

/*===========================================================================*/
/**
 * 単位行列化する．
 *
 * @return   求めた単位行列 ．
 */
Matrix3& Matrix3::identity()
{
	m[0][0] = 1.0f; m[0][1] = 0.0f; m[0][2] = 0.0f;
	m[1][0] = 0.0f; m[1][1] = 1.0f; m[1][2] = 0.0f;
	m[2][0] = 0.0f; m[2][1] = 0.0f; m[2][2] = 1.0f;

	return *this;
}

/*===========================================================================*/
/**
 * 拡大縮小行列を乗算．
 *
 * @param [in]     x x成分 ．
 * @param [in]     y y成分 ．
 * @param [in]     z z成分 ．
 * @return   乗算した行列 ．
 */
Matrix3& Matrix3::scale( float x, float y, float z )
{
	Matrix3	M( *this );
	Matrix3	s;

	s.setScale( x, y , z );

	*this = s * M;

	return *this;
}

/*===========================================================================*/
/**
 * 拡大縮小行列を乗算．
 *
 * @param [in]     scaleFactor xyz成分 ．
 * @return   乗算した行列 ．
 */
Matrix3& Matrix3::scale( const Vector3& scaleFactor )
{
	return scale( scaleFactor.x, scaleFactor.y, scaleFactor.z );
}

/*===========================================================================*/
/**
 * 拡大縮小行列を乗算．
 *
 * @param [in]     scaleFactor xyz成分 ．
 * @return   乗算した行列 ．
 */
Matrix3& Matrix3::sclae( float scaleFactor )
{
	return scale( scaleFactor, scaleFactor, scaleFactor );
}

/*===========================================================================*/
/**
 * 回転行列を乗算．
 *
 * @param [in]     angle 回転角度 ．
 * @param [in]     axisX ｘ軸成分．
 * @param [in]     axisY ｙ軸成分 ．
 * @param [in]     axisZ ｚ軸成分 ．
 * @return   乗算した行列 ．
 */
Matrix3& Matrix3::rotate( float angle, float axisX, float axisY, float axisZ )
{
	Matrix3	M( *this );
	Matrix3	r;
	
	r.setRotation( angle, axisX, axisY, axisZ );

	*this = r * M;

	return *this;
}

/*===========================================================================*/
/**
 * 回転行列を乗算．
 *
 * @param [in]     angle 回転角度 ．
 * @param [in]     axis xyz軸成分．
 * @return   乗算した行列 ．
 */
Matrix3& Matrix3::rotate( float angle, const Vector3& axis )
{
	return rotate( angle, axis.x, axis.y, axis.z );
}

/*===========================================================================*/
/**
 * 回転行列を乗算．
 *
 * @param [in]     q クォータニオン ．
 * @return   乗算した行列 ．
 */
Matrix3& Matrix3::rotate( const Quaternion& q )
{
	Matrix3	M( *this );
	Matrix3	r;

	r.setRotation( q );

	*this = r * M;

	return *this;
}

/*===========================================================================*/
/**
 * x軸の回転行列を乗算．
 *
 * @param [in]     x 角度．
 * @return   乗算した行列 ．
 */
Matrix3& Matrix3::rotateX( float angle )
{
	Matrix3	M( *this );
	Matrix3	r;
	
	r.setRotationX( angle );

	*this = r * M;

	return *this;
}

/*===========================================================================*/
/**
 * y軸の回転行列を乗算．
 *
 * @param [in]     y 角度 ．
 * @return   乗算した行列 ．
 */
Matrix3& Matrix3::rotateY( float angle )
{
	Matrix3	M( *this );
	Matrix3	r;

	r.setRotationY( angle );

	*this = r * M;

	return *this;
}

/*===========================================================================*/
/**
 * z軸の回転行列を乗算．
 *
 * @param [in]     z 角度 ．
 * @return   乗算した行列 ．
 */
Matrix3& Matrix3::rotateZ( float angle )
{
	Matrix3	M( *this );
	Matrix3	r;

	r.setRotationZ( angle );

	*this = r * M;

	return *this;
}

/*===========================================================================*/
/**
 * ヨー、ピッチ、ロールの回転行列を乗算．
 *
 * @param [in]     yaw   ヨー．
 * @param [in]     pitch ピッチ．
 * @param [in]     roll  ロール．
 * @return   乗算した行列 ．
 */
Matrix3& Matrix3::rotateYawPitchRoll( float yaw, float pitch, float roll )
{
	Matrix3	M( *this );
	Matrix3	r;

	r.setRotationYawPitchRoll( yaw, pitch, roll );

	*this = r * M;

	return *this;
}

/*===========================================================================*/
/**
 * 平行移動を乗算．
 *
 * @param [in]     x x座標．
 * @param [in]     y y座標．
 * @return   乗算した行列 ．
 */
Matrix3& Matrix3::translate( float x, float y )
{
	Matrix3	M( *this );
	Matrix3	t;

	t.setTranslation( x, y );

	*this = t * M;

	return *this;
}

/*===========================================================================*/
/**
 * 平行移動を乗算．
 *
 * @param [in]     translation 二次元座標．
 * @return   乗算した行列 ．
 */
Matrix3& Matrix3::translate( const Vector2& translation )
{
	return translate( translation.x, translation.y );
}

/*===========================================================================*/
/**
 * 逆行列にする．
 *
 * @return   変換した行列 ．
 */
Matrix3& Matrix3::inverse()
{
	Matrix3	M;
	float		det;
	float		invDet;

	M.m[0][0] = m[1][1] * m[2][2] - m[1][2]* m[2][1];
	M.m[0][1] = m[0][2] * m[2][1] - m[0][1]* m[2][2];
	M.m[0][2] = m[0][1] * m[1][2] - m[0][2]* m[1][1];
	M.m[1][0] = m[1][2] * m[2][0] - m[1][0]* m[2][2];
	M.m[1][1] = m[0][0] * m[2][2] - m[0][2]* m[2][0];
	M.m[1][2] = m[0][2] * m[1][0] - m[0][0]* m[1][2];
	M.m[2][0] = m[1][0] * m[2][1] - m[1][1]* m[2][0];
	M.m[2][1] = m[0][1] * m[2][0] - m[0][0]* m[2][1];
	M.m[2][2] = m[0][0] * m[1][1] - m[0][1]* m[1][0];

	det = m[0][0] * M.m[0][0]
		+ m[0][1] * M.m[1][0]
		+ m[0][2] * M.m[2][0];

	// 逆行列を求める事ができるか？(detが0.0の時は求めることができない)
	if( det == 0.0f )
	{
		return identity();
	}

	invDet = 1.0f / det;

	M.m[0][0] *= invDet;
	M.m[0][1] *= invDet;
	M.m[0][2] *= invDet;
	M.m[1][0] *= invDet;
	M.m[1][1] *= invDet;
	M.m[1][2] *= invDet;
	M.m[2][0] *= invDet;
	M.m[2][1] *= invDet;
	M.m[2][2] *= invDet;

	*this = M;

	return *this;
}

/*===========================================================================*/
/**
 * 転置行列にする．
 *
 * @return   変換した行列 ．
 */
Matrix3& Matrix3::transpose()
{
	Matrix3	M( *this );

	for( int i = 0; i < 3; ++i )
	{
		for( int j = 0; j < 3; ++j )
		{
			m[i][j] = M.m[j][i];
		}
	}

	return *this;
}

/*===========================================================================*/
/**
 * 転置逆行列にする．
 *
 * @return   変換した行列 ．
 */
Matrix3& Matrix3::inverseTranspose()
{
	inverse();

	transpose();

	return *this;
}

/*===========================================================================*/
/**
 * 逆行列を取得する．
 *
 * @return   逆行列．
 */
Matrix3 Matrix3::getInverse() const
{
	Matrix3	result( *this );

	result.inverse();

	return result;
}

/*===========================================================================*/
/**
 * 転置行列を取得する．
 *
 * @return   転置行列．
 */
Matrix3 Matrix3::getTranspose() const
{
	Matrix3	result( *this );

	result.transpose();

	return result;
}

/*===========================================================================*/
/**
 * 転置逆行列を取得する．
 *
 * @return   転置逆行列．
 */
Matrix3 Matrix3::getInverseTranspose() const
{
	Matrix3	result( *this );

	result.inverseTranspose();

	return result;
}

/*===========================================================================*/
/**
 * スケール値の設定．
 *
 * @param [in]     x x成分 ．
 * @param [in]     y y成分 ．
 * @param [in]     z z成分 ．
 * @return   設定した行列 ．
 */
Matrix3& Matrix3::setScale( float x, float y, float z )
{
	m[0][0]=    x; m[0][1] = 0.0f; m[0][2] = 0.0f;
	m[1][0]= 0.0f; m[1][1] =    y; m[1][2] = 0.0f;
	m[2][0]= 0.0f; m[2][1] = 0.0f; m[2][2] =    z;

	return *this;
}

/*===========================================================================*/
/**
 * スケール値の設定．
 *
 * @param [in]     scaleFactor xyz成分 ．
 * @return   設定した行列 ．
 */
Matrix3& Matrix3::setScale( const Vector3& scaleFactor )
{
	setScale( scaleFactor.x, scaleFactor.y, scaleFactor.z );

	return *this;
}

/*===========================================================================*/
/**
 * スケール値の設定．
 *
 * @param [in]     scaleFactor xyz成分 ．
 * @return   設定した行列 ．
 */
Matrix3& Matrix3::setScale( float scaleFactor )
{
	setScale( scaleFactor, scaleFactor, scaleFactor );

	return *this;
}

/*===========================================================================*/
/**
 * 回転行列の設定．
 *
 * @param [in]     angle 角度．
 * @param [in]     axisX x軸 ．
 * @param [in]     axisY y軸 ．
 * @param [in]     axisZ z軸 ．
 * @return   設定した行列 ．
 */
Matrix3& Matrix3::setRotation( float angle, float axisX, float axisY, float axisZ )
{
	float sinAngle;
	float cosAngle;
	float oneOinusCosAngle;
	float Len;

	sinAngle		 = Math::Sin( angle );
	cosAngle		 = Math::Cos( angle );
	oneOinusCosAngle = 1.0f - cosAngle;

	if( ( Len = Math::Sqrt( axisX * axisX + axisY * axisY + axisZ * axisZ ) ) != 0 )
	{
		axisX *= ( 1.0f / Len );
		axisY *= ( 1.0f / Len );
		axisZ *= ( 1.0f / Len );
	}

	m[0][0] = ( axisX * axisX ) + cosAngle * ( 1.0f - ( axisX * axisX ) );
	m[1][0] = ( axisX * axisY ) * oneOinusCosAngle - sinAngle * axisZ;
	m[2][0] = ( axisX * axisZ ) * oneOinusCosAngle + sinAngle * axisY;

	m[0][1] = ( axisX * axisY ) * oneOinusCosAngle + sinAngle * axisZ;
	m[1][1] = ( axisY * axisY ) + cosAngle * ( 1.0f - ( axisY * axisY ) );
	m[2][1] = ( axisY * axisZ ) * oneOinusCosAngle - sinAngle * axisX;

	m[0][2] = ( axisX * axisZ ) * oneOinusCosAngle - sinAngle * axisY;
	m[1][2] = ( axisY * axisZ ) * oneOinusCosAngle + sinAngle * axisX;
	m[2][2] = ( axisZ * axisZ ) + cosAngle * ( 1.0f - ( axisZ * axisZ ) );

	return *this;
}

/*===========================================================================*/
/**
 * 回転行列の設定．
 *
 * @param [in]     angle 角度．
 * @param [in]     axis  xyz軸 ．
 * @return   設定した行列 ．
 */
Matrix3& Matrix3::setRotation( float angle, const Vector3& axis )
{
	return setRotation( angle, axis.x, axis.y, axis.z );
}

/*===========================================================================*/
/**
 * 回転行列の設定．
 *
 * @param [in]     q クォータニオン．
 * @return   設定した行列 ．
 */
Matrix3& Matrix3::setRotation( const Quaternion& q )
{
	float xx, yy, zz;
	float xy, xz, yz;
	float wx, wy, wz;

	xx = q.x * q.x * 2.0f;
	yy = q.y * q.y * 2.0f;
	zz = q.z * q.z * 2.0f;
	xy = q.x * q.y * 2.0f;
	xz = q.x * q.z * 2.0f;
	yz = q.y * q.z * 2.0f;
	wx = q.w * q.x * 2.0f;
	wy = q.w * q.y * 2.0f;
	wz = q.w * q.z * 2.0f;

	m[0][0] = 1.0f - ( yy + zz );
	m[0][1] = xy + wz;
	m[0][2] = xz - wy;

	m[1][0] = xy - wz;
	m[1][1] = 1.0f - ( xx + zz );
	m[1][2] = yz + wx;

	m[2][0] = xz + wy;
	m[2][1] = yz - wx;
	m[2][2] = 1.0f - ( xx + yy );

	return *this;
}

/*===========================================================================*/
/**
 * X軸の回転行列の設定．
 *
 * @param [in]     angle 角度．
 * @return   設定した行列 ．
 */
Matrix3& Matrix3::setRotationX( float angle )
{
	Matrix3 M( *this );

	m[0][0] = 1.0f;
	m[0][1] = 0.0f;
	m[0][2] = 0.0f;

	m[1][0] = 0.0f;
	m[1][1] = Math::Cos( angle );
	m[1][2] = Math::Sin( angle );

	m[2][0] =  0.0f;
	m[2][1] = -M.m[1][2];
	m[2][2] =  M.m[1][1];

	return *this;
}

/*===========================================================================*/
/**
 * Y軸の回転行列の設定．
 *
 * @param [in]     angle 角度．
 * @return   設定した行列 ．
 */
Matrix3& Matrix3::setRotationY( float angle )
{
	Matrix3 M( *this );

	m[0][0] =  Math::Cos( angle );
	m[0][1] =  0.0f;
	m[0][2] = -M.m[2][0];

	m[1][0] = 0.0f;
	m[1][1] = 1.0f;
	m[1][2] = 0.0f;

	m[2][0] = Math::Sin( angle );
	m[2][1] = 0.0f;
	m[2][2] = M.m[0][0];

	return *this;
}

/*===========================================================================*/
/**
 * Z軸の回転行列の設定．
 *
 * @param [in]     angle 角度．
 * @return   設定した行列 ．
 */
Matrix3& Matrix3::setRotationZ( float angle )
{
	Matrix3 M( *this );

	m[0][0] = Math::Cos( angle );
	m[0][1] = Math::Sin( angle );
	m[0][2] = 0.0f;

	m[1][0] = -M.m[0][1];
	m[1][1] =  M.m[0][0];
	m[1][2] =  0.0f;

	m[2][0] = 0.0f;
	m[2][1] = 0.0f;
	m[2][2] = 1.0f;

	return *this;
}

/*===========================================================================*/
/**
 * ロール、ピッチ、ヨーから回転行列の設定．
 *
 * @param [in]     angle 角度．
 * @param [in]     angle 角度．
 * @param [in]     angle 角度．
 * @return   設定した行列 ．
 */
Matrix3& Matrix3::setRotationYawPitchRoll( float yaw, float pitch, float roll )
{
	Matrix3	matRoll;
	Matrix3	matPitch;
	Matrix3	matYaw;

	// ロール、ピッチ、ヨーから回転マトリクスを求める
	matPitch.setRotationX( pitch );
	matYaw.setRotationY( yaw );
	matRoll.setRotationZ( roll );

	// 回転マトリクスを合成する
	Matrix3 result = matRoll * matPitch;
	
	*this = result * matYaw;

	return *this;
}

/*===========================================================================*/
/**
 * 平行移動量の設定．
 *
 * @param [in]     x x座標．
 * @param [in]     y y座標．
 * @return   設定した行列 ．
 */
Matrix3& Matrix3::setTranslation( float x, float y )
{
	m[0][0] = 1.0f;
	m[0][1] = 0.0f;
	m[0][2] = 0.0f;

	m[1][0] = 0.0f;
	m[1][1] = 1.0f;
	m[1][2] = 0.0f;

	m[2][0] = x;
	m[2][1] = y;
	m[2][2] = 1.0f;

	return *this;
}

/*===========================================================================*/
/**
 * 平行移動量の設定．
 *
 * @param [in]     translation 2次元座標．
 * @return   設定した行列 ．
 */
Matrix3& Matrix3::setTranslation( const Vector2 translation )
{
	return setTranslation( translation.x, translation.y );
}

/*===========================================================================*/
/**
 * 座標変換．
 *
 * @param [in]     v 2次元座標．
 * @return   変換した2次元座標．
 */
Vector2 Matrix3::transform( const Vector2& v ) const
{
	Vector2 result;

	result.x = v.x * m[0][0]
			 + v.y * m[1][0]
			 +       m[2][0];
	result.y = v.x * m[0][1]
			 + v.y * m[1][1]
			 +       m[2][1];

	return result;
}

/*===========================================================================*/
/**
 * 座標変換．
 *
 * @param [in]     v 2次元座標．
 * @return   変換した2次元座標．
 */
Vector2 Matrix3::transformNormal( const Vector2& v ) const
{
	Vector2 result;

	result.x = v.x * m[0][0]
			 + v.y * m[1][0];
    result.y = v.x * m[0][1]
			 + v.y * m[1][1];

	return result;
}

/*===========================================================================*/
/**
 * 軸、位置の設定．
 *
 * @param [in]     axisX x軸の位置．
 * @return   設定した行列．
 */
Matrix3& Matrix3::setAxisX( const Vector3& axisX )
{
	m[0][0] = axisX.x;
	m[0][1] = axisX.y;
	m[0][2] = axisX.z;

	return *this;
}

/*===========================================================================*/
/**
 * 軸、位置の設定．
 *
 * @param [in]     axisY y軸の位置．
 * @return   設定した行列．
 */
Matrix3& Matrix3::setAxisY( const Vector3& axisY )
{
	m[1][0] = axisY.x;
	m[1][1] = axisY.y;
	m[1][2] = axisY.z;

	return *this;
}

/*===========================================================================*/
/**
 * 軸、位置の設定．
 *
 * @param [in]     axisZ z軸の位置．
 * @return   設定した行列．
 */
Matrix3& Matrix3::setAxisZ( const Vector3& axisZ )
{
	m[2][0] = axisZ.x;
	m[2][1] = axisZ.y;
	m[2][2] = axisZ.z;

	return *this;
}
/*===========================================================================*/
/**
 * ロールの取得．
 *
 * @return   ロール．
 */
float Matrix3::getRoll() const
{
	return Math::Atan( m[0][1], m[1][1] );
}

/*===========================================================================*/
/**
 * ピッチの取得．
 *
 * @return   ピッチ．
 */
float Matrix3::getPitch() const
{
	return Math::DegreeNormalize( Math::Asin( -m[2][1] ) );
}

/*===========================================================================*/
/**
 * ヨーの取得．
 *
 * @return   ヨー．
 */
float Matrix3::getYaw() const
{
	return Math::Atan( m[2][0], m[2][2] );
}

/*===========================================================================*/
/**
 * クォータニオンを取得．
 *
 * @return   クォータニオン．
 */
Quaternion Matrix3::getQuaternion() const
{
	Quaternion	q;
	float			tr;
	float			fourD;

	tr = m[0][0] + m[1][1] + m[2][2] + m[3][3];

	if( tr >= 1.0f )
	{
		fourD = 2.0f * Math::Sqrt( tr );
		q.w   = fourD / 4.0f;
		q.x   = ( m[1][2] - m[2][1] ) / fourD;
		q.y   = ( m[2][0] - m[0][2] ) / fourD;
		q.z   = ( m[0][1] - m[1][0] ) / fourD;
	}
	else 
	{
		float	qa[4];
		int		i, j, k;

		if( m[0][0] > m[1][1] )
		{
			i = 0;
		}
		else
		{
			i = 1;
		}
		if( m[2][2] > m[i][i] )
		{
			i = 2;
		}
		j = ( i + 1 ) % 3;
		k = ( j + 1 ) % 3;

		tr = m[i][i] - m[j][j] - m[k][k] + 1.0f;

		fourD = 2.0f * Math::Sqrt( tr );

		qa[i] = fourD / 4.0f;
		qa[j] = ( m[j][i] + m[i][j] ) / fourD;
		qa[k] = ( m[k][i] + m[i][k] ) / fourD;
		qa[3] = ( m[j][k] - m[k][j] ) / fourD;

		q.x = qa[0];
		q.y = qa[1];
		q.z = qa[2];
		q.w = qa[3];
	}

	return q;
}

/*===========================================================================*/
/**
 * 軸、位置の取得．
 *
 * @return   X軸．
 */
Vector3 Matrix3::getAxisX() const
{
	return Vector3( m[0][0], m[0][1], m[0][2] );
}

/*===========================================================================*/
/**
 * 軸、位置の取得．
 *
 * @return   Y軸．
 */
Vector3 Matrix3::getAxisY() const
{
	return Vector3( m[1][0], m[1][1], m[1][2] );
}

/*===========================================================================*/
/**
 * 軸、位置の取得．
 *
 * @return   Z軸．
 */
Vector3 Matrix3::getAxisZ() const
{
	return Vector3( m[2][0], m[2][1], m[2][2] );
}

/*===========================================================================*/
/**
 * (float*型)キャスト演算子オーバーロード．
 *
 * @return   型変換をした行列成分．
 */
Matrix3::operator float* ()
{
	return reinterpret_cast<float*>(m);
}

/*===========================================================================*/
/**
 * (const flost*型)キャスト演算子オーバーロード．
 *
 * @return   型変換をした行列成分．
 */
Matrix3::operator const float* ()
{
	return reinterpret_cast<const float*>(m);
}

/*===========================================================================*/
/**
 * (+)単項演算子オーバーロード．
 *
 * @return 結果のMatrix3．
 */
Matrix3 Matrix3::operator + () const
{
	return *this;
}

/*===========================================================================*/
/**
 * (-)単項演算子オーバーロード．
 *
 * @return 結果のMatrix3.
 */
Matrix3 Matrix3::operator - () const
{
	return Matrix3( -m[0][0], -m[0][1], -m[0][2],
					-m[1][0], -m[1][1], -m[1][2],
					-m[2][0], -m[2][1], -m[2][2] );
}

/*===========================================================================*/
/**
 * (+=) 演算子オーバーロード．
 * 
 * @param [in]  M Matrix3．
 * @return 結果のMatrix3．
 */
Matrix3& Matrix3::operator += ( const Matrix3& M )
{
	for( int i = 0; i < 3; ++i )
	{
		for( int j = 0; j < 3; ++j )
		{
			m[i][j] += M.m[i][j];
		}
	}

	return *this;
}

/*===========================================================================*/
/**
 * (-=) 演算子オーバーロード．
 * 
 * @param [in]  M Matrix3．
 * @return 結果のMatrix3．
 */
Matrix3& Matrix3::operator -= ( const Matrix3& M )
{
	for( int i = 0; i < 3; ++i )
	{
		for( int j = 0; j < 3; ++j )
		{
			m[i][j] -= M.m[i][j];
		}
	}

	return *this;
}

/*===========================================================================*/
/**
 * (*=) 演算子オーバーロード．
 * 
 * @param [in]  M Matrix3．
 * @return 結果のMatrix3．．
 */
Matrix3& Matrix3::operator *= ( const Matrix3& M )
{
	Matrix3	result;

	for( int i = 0; i < 3; ++i )
	{
		for( int j = 0; j < 3; ++j )
		{
			result.m[i][j] = m[i][0] * M.m[0][j]
						   + m[i][1] * M.m[1][j]
						   + m[i][2] * M.m[2][j];
		}
	}

	*this = result;

	return *this;
}

/*===========================================================================*/
/**
 * (*=) 演算子オーバーロード．
 * 
 * @param [in]  s スカラー．
 * @return 結果のMatrix3．
 */
Matrix3& Matrix3::operator *= ( float s )
{
	for( int i = 0; i < 3; ++i )
	{
		for( int j = 0; j < 3; ++j )
		{
			m[i][j] = m[i][j] * s;
		}
	}

	return *this;
}

/*===========================================================================*/
/**
 * (/=)演算子オーバーロード．
 * 
 * @param [in]  s スカラー．
 * @return 結果のMatrix3．
 */
Matrix3& Matrix3::operator /= ( float s )
{
	(*this) *= ( 1.0f / s );

	return *this;
}

/***  以下非メンバ関数 *******************************************************/

/*===========================================================================*/
/**
 * (+)演算子オーバーロード．
 * 
 * @param [in]  m1 Matrix3．
 * @param [in]  m2 Matrix3．
 * @return 結果のMatrix3．
 */
const Matrix3 operator + ( const Matrix3& m1, const Matrix3& m2 )
{
	Matrix3	result( m1 );

	result += m2;

	return result;
}

/*===========================================================================*/
/**
 * (-)演算子オーバーロード．
 * 
 * @param [in]  m1 Matrix3．
 * @param [in]  m2 Matrix3．
 * @return 結果のMatrix3．
 */
const Matrix3 operator - ( const Matrix3& m1, const Matrix3& m2 )
{
	Matrix3	result( m1 );

	result -= m2;

	return result;
}

/*===========================================================================*/
/**
 * (*)演算子オーバーロード．
 * 
 * @param [in]  m1 Matrix3．
 * @param [in]  m2 Matrix3．
 * @return 結果のMatrix3．
 */
const Matrix3 operator * ( const Matrix3& m1, const Matrix3& m2 )
{
	Matrix3	result( m1 );

	result *= m2;

	return result;
}

/*===========================================================================*/
/**
 * (*) 演算子オーバーロード．
 * 
 * @param [in]  M Matrix3．
 * @param [in]  s スカラー．
 * @return 結果のMatrix3．
 */
const Matrix3 operator * ( const Matrix3& M, const float s )
{
	Matrix3	result( M );

	result *= s;

	return result;
}

/*===========================================================================*/
/**
 * (*) 演算子オーバーロード．
 * 
 * @param [in]  s スカラー．
 * @param [in]  M Matrix3．
 * @return 結果のMatrix3．
 */
const Matrix3 operator * ( const float s, const Matrix3& M )
{
	return M * s;
}

/*===========================================================================*/
/**
 * (/) 演算子オーバーロード．
 * 
 * @param [in]  M Matrix3．
 * @param [in]  s スカラー．
 * @return 結果のMatrix3．
 */
const Matrix3 operator / ( const Matrix3& M, const float s )
{
	return M * ( 1.0f / s );
}

/*===========================================================================*/
/**
 * (==) 演算子オーバーロード．
 * 
 * @param [in]  m1 Matrix3．
 * @param [in]  m2 Matrix3．
 * @return 比較結果．
 */
bool operator == ( const Matrix3& m1, const Matrix3& m2 )
{
	for( int i = 0; i < 3; ++i )
	{
		for( int j = 0; j < 3; ++j )
		{
			if( m1.m[i][j] != m2.m[i][j] )
			{
				return false;
			}
		}
	}

	return true;
}

/*===========================================================================*/
/**
 * (!=) 演算子オーバーロード．
 * 
 * @param [in]  m1 Matrix3．
 * @param [in]  m2 Matrix3．
 * @return 比較結果．
 */
bool operator != ( const Matrix3& m1, const Matrix3& m2 )
{
	return !( m1 == m2 );
}

} // namespace tglib


/*========= End of File =====================================================*/
